package com.maijinjie.common.kindeditor;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.maijinjie.common.util.ImgResize;
import com.maijinjie.common.util.StringUtil;

/**
 * Kindeditoer图片上传
 * @version 1.0
 * @author GhostarX ( 王欣逸 ) 100992995@qq.com
 */
@SuppressWarnings("serial")
public class KindeditorServlet extends HttpServlet {
	/** 配置路径 */
	private static String configPath = "resources/config/kindEditor";
	/** 上传文件的地址类型 */
	private boolean isShowDomain;
	/** 图片域名 */
	private String domain;
	/** 设置文件存储位置 */
	private String basicPath;
	/** 设置编码格式 */
	private String charset;
	/** 图片上传类型 */
	private String imageType;
	/** Flash上传类型 */
	private String flashType;
	/** flv上传类型 */
	private String flvType;
	/** 媒体上传类型 */
	private String mediaType;
	/** 文件上传类型 */
	private String fileType;
	/** 文件最大限制(100m) */
	private long maxSize;
	/** 是否压缩图片 */
	private boolean isResize;
	/** 图片压缩的最大宽度 */
	private int imgResizeMaxWidth;
	/** 图片压缩的大小上线 */
	private int imgResizeMaxSize;
	
	/**
	 * 构造器
	 */
	public KindeditorServlet(){
		ResourceBundle bundle = ResourceBundle.getBundle(configPath);
		this.basicPath = bundle.getString("basicPath");
		this.charset = bundle.getString("charset");
		this.imageType = bundle.getString("imageType");
		this.flashType = bundle.getString("flashType");
		this.flvType = bundle.getString("flvType");
		this.mediaType = bundle.getString("mediaType");
		this.fileType = bundle.getString("fileType");
		this.maxSize = StringUtil.getLong(bundle.getString("maxSize"));
		this.isResize = "true".equals(bundle.getString("isResize"))?true:false;
		this.domain = bundle.getString("domainUrl");
		this.isShowDomain = "true".equals(bundle.getString("isShowDomain"))?true:false;
		this.imgResizeMaxWidth = StringUtil.getInt(bundle.getString("imgResizeMaxWidth"));
		this.imgResizeMaxSize = StringUtil.getInt(bundle.getString("imgResizeMaxSize"));
	}
	
	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//文件保存目录绝对路径的开头
		StringBuffer savePath = new StringBuffer(request.getSession().getServletContext().getRealPath("/")).append(basicPath);
		//文件保存目录相对路径URL的开头
		StringBuffer saveUrl = new StringBuffer();
		if(this.isShowDomain){//是否显示域名
			saveUrl.append(this.domain);
		}
		saveUrl.append(this.basicPath);
			
		//定义允许上传的文件扩展名
		HashMap<String, String> extMap = new HashMap<String, String>();
		extMap.put("image", this.imageType);
		extMap.put("flash", this.flashType);
		extMap.put("flv", this.flvType);
		extMap.put("media", this.mediaType);
		extMap.put("file", this.fileType);

		response.setContentType("text/html; charset="+this.charset);

		if(!ServletFileUpload.isMultipartContent(request)){
			writeHTML(getError("请选择文件。"), response);
			return;
		}
		//检查目录
		File uploadDir = new File(savePath.toString());
		if(!uploadDir.isDirectory()){
			uploadDir.mkdirs();
		}
		//检查目录写权限
		if(!uploadDir.canWrite()){
			writeHTML(getError("上传目录没有写权限。"), response);
			return;
		}
		String dirName = request.getParameter("dir");
		if (dirName == null) {
			dirName = "image";
		}
		if(!extMap.containsKey(dirName)){
			writeHTML(getError("目录名不正确。"), response);
			return;
		}
		//创建文件夹
		savePath.append(dirName).append("/");
		saveUrl.append(dirName).append("/");
		File saveDirFile = new File(savePath.toString());
		if (!saveDirFile.exists()) {
			saveDirFile.mkdirs();
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
		String yyyymm = sdf.format(new Date());
		savePath.append(yyyymm).append("/");
		saveUrl.append(yyyymm).append("/");
		File dirFile = new File(savePath.toString());
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		FileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(factory);
		upload.setHeaderEncoding(this.charset);
		List<FileItem> items = null;
		try {
			items = upload.parseRequest(request);
			Iterator<FileItem> itr = items.iterator();
			while (itr.hasNext()) {
				FileItem item = itr.next();
				String fileName = item.getName();
				if (!item.isFormField()) {
					//检查文件大小
					if(item.getSize() > this.maxSize){
						writeHTML(getError("上传文件大小超过限制。不能超过"+this.maxSize+"kb"), response);
						return;
					}
					//检查扩展名
					String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
					if(!Arrays.<String>asList(extMap.get(dirName).split(",")).contains(fileExt)){
						writeHTML(getError("上传文件扩展名是不允许的扩展名。\n只允许" + extMap.get(dirName) + "格式。"), response);
						return;
					}

					String newFileName = UUID.randomUUID().toString().replace("-", "").toUpperCase() + "." + fileExt;
					File uploadedFile = new File(savePath.toString(), newFileName);
					item.write(uploadedFile);

					String imgPath = new StringBuffer(saveUrl).append(newFileName).toString();//图片路径
					if(isResize){//是否压缩图片
						resize(uploadedFile); //压缩图片
					}
					
					writeHTML(getSuccessJson(imgPath), response);
				}
			}
		} catch (FileUploadException e1) {
			writeHTML(getError(e1.getMessage()), response);
			return;
		} catch (Exception e) {
			writeHTML(getError(e.getMessage()), response);
			e.printStackTrace();
			return;
		}
	}
	/**
	 * 检查
	 * @return boolean
	 * @version 1.0
	 * @author GhostarX ( 王欣逸 ) 100992995@qq.com 18902499340
	 * @data 2013-8-16 下午2:13:28
	 */
	public boolean check(){
		boolean isPass = false;
		
		return isPass;
	}
	/**
	 * 压缩图片
	 * @param imgFile
	 */
	public void resize(File imgFile){
		try {
			int width = ImageIO.read(imgFile).getWidth(null);
			if(this.imgResizeMaxWidth<width){ //图片宽度超过750像素
				ImgResize.resize(imgFile, ImgResize.TYPE_FOR_WIDTH, this.imgResizeMaxWidth, 0, "");
			} else if(this.imgResizeMaxSize<imgFile.length()/1024){ //图片大小超过200KB则进行原尺寸等比例压缩
				ImgResize.resize(imgFile, ImgResize.TYPE_FOR_WIDTH, width, 0, "");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doPost(req, resp);
	}

	/**
	 * 获取正常图片输出
	 * @param imgPath
	 * @return
	 */
	private String getSuccessJson(String imgPath) {
		StringBuffer obj = new StringBuffer();
		obj.append("{");
		obj.append("\"").append("error").append("\":");
		obj.append(0).append(",");
		obj.append("\"").append("url").append("\":");
		obj.append("\"").append(imgPath).append("\"");
		obj.append("}");
		return obj.toString();
	}

	/**
	 * 获取错误信息
	 * @param message 错误信息
	 * @return String Json对象转换而成
	 */
	private String getError(String message) {
		StringBuffer obj = new StringBuffer();
		obj.append("{");
		obj.append("\"").append("error").append("\":");
		obj.append(1).append(",");
		obj.append("\"").append("message").append("\":");
		obj.append("\"").append(message).append("\"");
		obj.append("}");
		return obj.toString();
	}
	
	/**
	 * 输出HTML代码
	 * @param html html代码
	 * @param response
	 * @throws IOException 
	 */
	public void writeHTML(String html, HttpServletResponse response) throws IOException{
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter writer = null;;
		try {
			writer = response.getWriter();
			writer.write(html);
			writer.flush();
		} catch (IOException e) {
			throw e;
		} finally {
			if(null!=writer){
				writer.close();
			}
		}
	}
}
